﻿using Avalonia.Controls;
using Avalonia.Controls.Shapes;

using LightCAD.Core;
using LightCAD.Core.Elements;
using LightCAD.Runtime;
using netDxf;
using netDxf.Entities;
using SkiaSharp;

using System;
using System.Collections;
using System.Collections.Generic;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static LightCAD.Core.Elements.LcQLeader;

// ReSharper disable BadExpressionBracesIndent
// ReSharper disable BadIndent

namespace LightCAD.Drawing
{
    public class QleaderAction : ElementAction
    {
        public static string CommandName;
        public static LcCreateMethod[] CreateMethods;
        private List<Vector2d> points;
        /// <summary>
        /// 引线第一个点
        /// </summary>
        private Vector2d? startPoint { get; set; }
        /// <summary>
        /// 每节线的开始点
        /// </summary>
        private Vector2d? firstPoint { get; set; }
        /// <summary>
        /// 每节线的第二个点
        /// </summary>
        private Vector2d? secondPoint { get; set; }
        /// <summary>
        /// 临时集合
        /// </summary>
        private List<QleaderSegment> Segments { get; set; }
        /// <summary>
        /// 箭头的点
        /// </summary>
        private List<Vector2d> ArrowPoints { get; set; }
        static QleaderAction()
        {

            CreateMethods = new LcCreateMethod[3];
            CreateMethods[0] = new LcCreateMethod()
            {
                Name = "CreateQLeader",
                Description = "创建引线",
                Steps = new LcCreateStep[]
                {
                    new LcCreateStep { Name=  "Step0", Options= "指定第一个引线点或 [设置(S)] <设置>:" },
                    new LcCreateStep { Name=  "Step1", Options= "指定下一点:" },
                    new LcCreateStep { Name=  "Step2", Options= "指定下一点:" },
                }
            };

        }

        internal static void Initilize()
        {
            ElementActions.QLeader = new QleaderAction();
            LcDocument.ElementActions.Add(BuiltinElementType.QLeader, ElementActions.QLeader);
        }
        private InElementsInputer InElementsInputer { get; set; }
        private ElementSetInputer ElementInputers { get; set; }
        private ElementInputer ElementInputer { get; set; }
        private CmdTextInputer CmdTextInputer { get; set; }
        private PointInputer PointInputer { get; set; }
        private QleaderAction() { }
        public QleaderAction(DocumentRuntime docRt) : base(docRt)
        {
            docRt.CommandCtrl.WriteInfo("命令：QLEADER");
        }

        public async void ExecCreate(string[] args = null)
        {
            //DocumentManager.CurrentRecorder.BeginAction("QLEADER");
            this.StartCreating();
            this.Segments = new List<QleaderSegment>();
            this.ArrowPoints = new List<Vector2d>();
            var curMethod = CreateMethods[0];
            this.PointInputer = new PointInputer(this.docRt);
            this.points = new List<Vector2d>();
        Step0:
            var step0 = curMethod.Steps[0];
            var result0 = await PointInputer.Execute(step0.Options);
            if (PointInputer.isCancelled) { this.Cancel(); return; }
            // zcb: 增加Res0为空的判定
            if (result0 == null)
            {
                this.Cancel();
                goto End;
            }
            if (result0.Value == null)
            {
                if (result0.Option != null)
                {
                    goto Step0;
                    //TODO:AutoCAD画线输入一个数字，是怎么确定点的？
                }
                else
                    goto Step1;
            }
            else
            {

                this.startPoint = (Vector2d)result0.Value;
                this.firstPoint = (Vector2d)result0.Value;
                goto Step1;
            }
        Step1:
            var step1 = curMethod.Steps[1];
            var result1 = await PointInputer.Execute(step1.Options);
            if (PointInputer.isCancelled)
            {
                this.Cancel();
                return;
            }
            if (result1.Value == null)
            {
                if (result0.Option != null)
                {

                }
                else {
                    goto Step2;
                }
            }
            else
            {
                this.secondPoint = (Vector2d)result1.Value;
                QleaderSegment pl = new QleaderSegment();
                pl.Start = (Vector2d)this.firstPoint;
                pl.End = (Vector2d)this.secondPoint;
                Segments.Add(pl);
                this.firstPoint = (Vector2d)result1.Value;

                #region
                LcLine lcline = new LcLine();
                lcline.Start = pl.Start;
                lcline.End = pl.End;
                var radian = lcline.Angle;

                var startve = new Vector2d(pl.Start.X, pl.Start.Y);
                var arrowtwove = new Vector2d(pl.Start.X + 100, pl.Start.Y + 30);
                var arrowendve = new Vector2d(pl.Start.X + 100, pl.Start.Y - 30);
                var angle = Utils.RadianToDegree(radian);
                arrowtwove = Vector2d.Rotate(arrowtwove, startve, angle);
                arrowendve = Vector2d.Rotate(arrowendve, startve, angle);

                ArrowPoints.Add(startve);
                ArrowPoints.Add(arrowtwove);
                ArrowPoints.Add(arrowendve);
                #endregion
                CreateQleader(Segments, ArrowPoints);
                goto Step2;
            }

        Step2:
            var step2 = curMethod.Steps[2];
            var result2 = await PointInputer.Execute(step2.Options);
            if (PointInputer.isCancelled)
            {
                this.Cancel();
                goto End;
            }
            if (result2.Value == null)
            {
                if (result1.Option != null)
                {

                }
                else
                {
                    goto Step2;
                }
            }
            else
            {
                this.secondPoint = (Vector2d)result2.Value;
                QleaderSegment pl = new QleaderSegment();
                pl.Start = (Vector2d)this.firstPoint;
                pl.End = (Vector2d)this.secondPoint;
                Segments.Add(pl);
                CreateQleader(Segments, ArrowPoints);
            }
        End:
            this.EndCreating();

        }

        public override void Cancel()
        {
            base.Cancel();
            this.vportRt.SetCreateDrawer(null);
        }
        private void test()
        {
            // this.vportRt.Renderer.DrawRect()
        }

        public override void CreateElement(LcElement element, Matrix3d matrix)
        {
            var grp = element as LcGroup;
            foreach (var ele in grp.Elements)
            {
                var eleAction = (ele.RtAction as ElementAction);
                eleAction.CreateElement(ele, matrix);
            }
        }
        public override void CreateElement(LcElement element, Vector2d basePoint, double scaleFactor)
        {
            var grp = element as LcGroup;
            foreach (var ele in grp.Elements)
            {
                var eleAction = (ele.RtAction as ElementAction);
                eleAction.CreateElement(ele, basePoint, scaleFactor);
            }

        }
        public override void CreateElement(LcElement element, Vector2d basePoint, Vector2d scaleVector)
        {
            var grp = element as LcGroup;
            foreach (var ele in grp.Elements)
            {
                var eleAction = (ele.RtAction as ElementAction);
                eleAction.CreateElement(ele, basePoint, scaleVector);
            }

        }

        public override ControlGrip[] GetControlGrips(LcElement element)
        {
            var group = element as LcGroup;
            var grips = new List<ControlGrip>();
            
            return grips.ToArray();
        }

        private bool CreateQleader(List<QleaderSegment> Segments, List<Vector2d> ArrowPoints)
        {
            var doc = this.docRt.Document;
            DocumentManager.CurrentRecorder.BeginAction("QLEADER");
            var Qleader = doc.CreateObject<LcQLeader>();
            Qleader.Segments = Segments;
            Qleader.ArrowPoints = ArrowPoints;
            doc.ModelSpace.InsertElement(Qleader);
            this.docRt.Action.ClearSelects();
            DocumentManager.CurrentRecorder.EndAction();
            return true;
        }

        public override void DrawAuxLines(SKCanvas canvas)
        {
            if (firstPoint != null)
            {
                var mp = this.vportRt.PointerMovedPosition.ToVector2d();
                var wcs_mp = this.vportRt.ConvertScrToWcs(mp);
                DrawAuxLine(canvas, firstPoint.Value, wcs_mp);
            }
        }

        private void DrawAuxLine(SKCanvas canvas, Vector2d p0, Vector2d p1)
        {
            var sk_pre = this.vportRt.ConvertWcsToScr(p0).ToSKPoint();
            var sk_p = this.vportRt.ConvertWcsToScr(p1).ToSKPoint();
            //辅助元素的颜色 
            canvas.DrawLine(sk_pre, sk_p, Constants.auxElementPen);
            //辅助曲线的颜色，包括辅助长度，辅助角度等
        }

        public override void Draw(SKCanvas canvas, LcElement element, Matrix3d matrix)
        {
            var grp = element as LcQLeader;
            foreach (var ele in grp.Segments)
            {
                
                var mstart = matrix.MultiplyPoint(ele.Start);
                var mend = matrix.MultiplyPoint(ele.End);
                var start = this.vportRt.ConvertWcsToScr(mstart).ToSKPoint();
                var end = this.vportRt.ConvertWcsToScr(mend).ToSKPoint();
                var pen = this.GetDrawPen(element);
                if (pen == Constants.defaultPen)
                {
                    using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                    {
                        canvas.DrawLine(start, end, elePen);
                    }
                }
                else
                {
                    canvas.DrawLine(start, end, pen);
                }
            }
            if (grp.ArrowPoints?.Count > 0) {
                var path = new SKPath();
                path.FillType = SKPathFillType.EvenOdd;

                int i = 1;
                foreach (var ele in grp.ArrowPoints)
                {
                    var mstpoint = matrix.MultiplyPoint(ele);
                    var point = this.vportRt.ConvertWcsToScr(mstpoint).ToSKPoint();
                    if (i == 1)
                    {
                        //外圈 顺时针
                        path.MoveTo(point.X, point.Y);    //起点
                    }
                    else
                    {
                        path.LineTo(point.X, point.Y);
                    }
                    i++;
                }
                path.Close();
                using (var elePen = new SKPaint { Color = new SKColor(element.GetColorValue()), IsStroke = true })
                {
                    elePen.Color = SKColors.Red;
                    elePen.Style = SKPaintStyle.StrokeAndFill;
                    elePen.IsAntialias = true;
                    elePen.StrokeWidth = 2;
                    //绘制路径
                    canvas.DrawPath(path, elePen);
                }
            }
        }

        public override void SetDragGrip(LcElement element, string gripName, Vector2d position, bool isEnd)
        {
            //var qLeader = element as LcQLeader;
            //_line = qLeader;
            //if (!isEnd)
            //{
            //    _gripName = gripName;
            //    _position = position;
            //}
            //else
            //{
            //    if (gripName == "Start")
            //        line.Set(start: position);
            //    else if (gripName == "End")
            //    {
            //        _line.Set(end: position);
            //    }
            //}
            //  DocumentManager.CurrentRecorder.EndAction();
        }

        public override void DrawDragGrip(SKCanvas canvas)
        {
            //if (_circle == null) return;

            //var center = this.vportRt.ConvertWcsToScr(_circle.Center);
            //var r = this.vportRt.ConvertWcsToScr(_circle.Radius);
            //if (_gripName == "Center")
            //    center = this.vportRt.ConvertWcsToScr(_position);
            //else
            //{
            //    var wr = Vector2d.Distance(_circle.Center, _position);
            //    r = this.vportRt.ConvertWcsToScr(wr);
            //}
            //canvas.DrawCircle(center.ToSKPoint(), (float)r, Constants.draggingPen);
        }
    }
}